package com.hps.boot.seata.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hps.boot.seata.entity.StorageTbl;
import com.hps.boot.seata.mapper.StorageTblMapper;
import com.hps.boot.seata.service.IStorageTblService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalLock;
import io.seata.spring.annotation.GlobalTransactional;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoProperties.Storage;
import org.springframework.stereotype.Service;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author heps
 * @since 2020-09-28
 */
@Service
public class StorageTblServiceImpl extends ServiceImpl<StorageTblMapper, StorageTbl> implements IStorageTblService {

  @Resource
  private DataSource dataSource;

  @Override
  public void deduct(String commodityCode, int count) {
    //There is a latent isolation problem here.
    //I hope that users can solve it and deepen their understanding of seata isolation.
    //At the bottom I will put a reference solution.
    StorageTbl storage = baseMapper.selectOne(new QueryWrapper<StorageTbl>()
        .lambda()
        .eq(StorageTbl::getCommodityCode, commodityCode)
    );
    storage.setCount(storage.getCount() - count);
    baseMapper.updateById(storage);
  }

  @GlobalLock
  public StorageTbl get(Integer id) {
    return baseMapper.selectById(id);
  }

  /**
   * 0.8.0 release
   *
   * @throws SQLException
   */
  @Override
  @GlobalTransactional
  public void batchUpdate() throws SQLException {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    try {
      connection = dataSource.getConnection();
      connection.setAutoCommit(false);
      String sql = "update storage_tbl set count = ?" +
          "    where id = ? and commodity_code = ?";
      preparedStatement = connection.prepareStatement(sql);
      preparedStatement.setInt(1, 100);
      preparedStatement.setLong(2, 1);
      preparedStatement.setString(3, "2001");
      preparedStatement.addBatch();
      preparedStatement.setInt(1, 200);
      preparedStatement.setLong(2, 2);
      preparedStatement.setString(3, "2002");
      preparedStatement.addBatch();
      preparedStatement.setInt(1, 300);
      preparedStatement.setLong(2, 3);
      preparedStatement.setString(3, "2003");
      preparedStatement.addBatch();
      preparedStatement.executeBatch();
      connection.commit();
      System.out.println(1 / 0);
    } catch (Exception e) {
      throw e;
    } finally {
      connection.close();
      preparedStatement.close();
    }
  }

  /**
   * 0.8.0 release
   *
   * @throws SQLException
   */
  @Override
  @GlobalTransactional
  public void batchDelete() throws SQLException {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    try {
      connection = dataSource.getConnection();
      connection.setAutoCommit(false);
      String sql = "delete from storage_tbl where  count = ? and commodity_code = ?";
      preparedStatement = connection.prepareStatement(sql);
      preparedStatement.setInt(1, 11);
      preparedStatement.setString(2, "2001");
      preparedStatement.addBatch();
      preparedStatement.setInt(1, 22);
      preparedStatement.setString(2, "2002");
      preparedStatement.addBatch();
      preparedStatement.setInt(1, 33);
      preparedStatement.setString(2, "2003");
      preparedStatement.addBatch();
      preparedStatement.executeBatch();
      connection.commit();
      System.out.println(1 / 0);
    } catch (Exception e) {
      throw e;
    } finally {
      connection.close();
      preparedStatement.close();
    }
  }
}
